package net.sf.calibur.transport;

import java.io.InputStream;
import java.security.MessageDigest;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class CipherContext {
	static {
		System.loadLibrary("keygen");
	}

	final static int KEY_LEN = 24;
	final static String CryptoAlgorithm = "DESede";
	final static long MASK = 0X00FF;

	private long[] salt;
	private byte[] sessionKey;
	private byte[] key;
	private Cipher cipher;

	CipherContext(Session session, MessageDigest digest) {
		salt = new long[2];
		salt[0] = salt[1] = 1L;

		key = new byte[KEY_LEN];
		try {
			sessionKey = digest.digest(session.getKey().getBytes("UTF-8"));

			// 初始化cipher
			cipher = Cipher.getInstance(CryptoAlgorithm);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	byte[] getSessionKey() {
		return this.sessionKey;
	}

	byte[] getKey() {
		return this.key;
	}

	long getSalt(long sequ) {
		long curr;
		if (sequ < 2) {
			salt[0] = salt[1] = curr = 1L;
		} else {
			curr = salt[0] + salt[1];
			salt[0] = salt[1];
			salt[1] = curr;
		}

		return curr;
	}

	public static native void initKey();
	public static native void createKey(long cts, long sts, long sequ, byte[] key);

	void refresh(Session session) {
		createKey(session.getRequestTimestamp(),
				session.getEstablishTimestamp(),
				session.getReceiveSequence(), key);
	}

	CipherInputStream getCipherInputStream(Session session, InputStream src)
			throws Exception {
		refresh(session);
		// 生成密钥
		SecretKey deskey = new SecretKeySpec(key, CipherContext.CryptoAlgorithm);
		// 解密
		cipher.init(Cipher.DECRYPT_MODE, deskey);
		CipherInputStream stream = new CipherInputStream(src, cipher);
		return stream;
	}
}
